package com.je.core.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.je.cache.service.config.BackCacheManager;
import com.je.cache.service.config.FrontCacheManager;
import com.je.cache.service.rbac.DeptChildCacheManager;
import com.je.core.exception.PlatformException;
import com.je.core.exception.PlatformExceptionEnum;
import com.je.core.mapper.query.Condition;
import com.je.core.mapper.query.ConditionEnum;
import com.je.core.mapper.query.Order;
import com.je.core.mapper.query.Query;
import com.je.core.util.*;
import com.je.core.util.bean.DynaBean;
import com.je.develop.service.FuncPermManager;
import com.je.develop.vo.FuncPermVo;
import com.je.develop.vo.FuncQueryStrategy;
import com.je.develop.vo.FuncSqlPermVo;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.ibatis.extension.enums.Conditions;
import com.je.rbac.model.EndUser;
import com.je.rbac.model.Role;
import com.je.rbac.model.Sentry;
import com.je.rbac.model.UserLeader;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 查询条件构建器
 *
 * @author wangmm@ketr.com.cn
 * @date 2019/12/28
 */
@Component
public class QueryBuilder {

    private static final Logger logger = LoggerFactory.getLogger(QueryBuilder.class);

    /**
     * object2string
     */
    private static final Function<Object, String> O2S = object -> object != null ? object.toString() : null;

    /**
     * object2boolean
     */
    private static final Predicate<Object> O2B = object -> object != null && "1".equals(object.toString());

    @Autowired
    private MetaService metaService;

    @Autowired
    private FuncPermManager funcPermManager;

    public static void condition(ConditionsWrapper wrapper, Condition p) {
        condition(wrapper, p, null);
    }

    /**
     * condition
     *
     * @param wrapper   条件构造器
     * @param p         条件对象
     * @param variables 变量
     * @return void
     */
    public static void condition(ConditionsWrapper wrapper, Condition p, Map<String, Object> variables) {
        //校验是否传入条件
        if (p == null || StringUtils.isBlank(p.getType())) {
            return;
        }
        //是否是OR 默认AND
        wrapper.or("or".equalsIgnoreCase(p.getCn()) && !wrapper.isEmpty());
        //字段名，去除空格防Sql注入
        String code = trimBlank(p.getCode());
//        if (code != null && !code.trim().matches("^[a-zA-Z\\$_][a-zA-Z\\d_]*$")) {
//            throw new PlatformException("条件不合法，请传入正规列名", PlatformExceptionEnum.UNKOWN_ERROR);
//        }
        //条件类型枚举
        ConditionEnum type = ConditionEnum.getCondition(p.getType());
        //
        Object value = p.getValue();
        //替换变量值
        if (ConditionEnum.AND != type && ConditionEnum.OR != type
                && ConditionEnum.IN != type && ConditionEnum.NOT_IN != type
                && ConditionEnum.IN_SELECT != type && ConditionEnum.NOT_IN_SELECT != type
                && ConditionEnum.BETWEEN != type
                && variables != null && !variables.isEmpty()) {
            String conditionStr = O2S.apply(p.getValue());
            value = formatSqlParameter(variables, conditionStr);
        }
        //字段条件
        if (ConditionEnum.BETWEEN == type) {
            //值转换为集合
            List list = parseList(p.getValue());
            if (list == null || list.size() < 2) {
                logger.error(" BETWEEN condition value error. -{}", p.getValue());
                throw new PlatformException(String.format(" BETWEEN condition value error. -%s", p.getValue()), PlatformExceptionEnum.JE_CORE_ERROR);
            }
            wrapper.between(code, list.get(0), list.get(1));
        } else if (ConditionEnum.EQ == type) {
            wrapper.eq(code, value);
        } else if (ConditionEnum.GE == type) {
            wrapper.ge(code, value);
        } else if (ConditionEnum.GT == type) {
            wrapper.gt(code, value);
        } else if (ConditionEnum.IN == type || ConditionEnum.NOT_IN == type) {
            //值转换为集合
            List list = parseList(p.getValue());
            //不管是否为空 都应执行
            if (ConditionEnum.IN == type) {
                wrapper.in(code, list);
            } else {
                wrapper.notIn(code, list);
            }
        } else if (ConditionEnum.IN_SELECT == type || ConditionEnum.NOT_IN_SELECT == type) {
            JSONObject inSelect = JSONObject.parseObject(O2S.apply(p.getValue()));
            //子查询表
            String table = trimBlank(inSelect.getString("table"));
            String fieldCode = trimBlank(inSelect.getString("code"));
            //子查询条件
            List<Condition> conditions = JSON.parseArray(inSelect.getString("conditions"), Condition.class);
            if (conditions.isEmpty()) {
                return;
            }
            //构建子查询where条件
            ConditionsWrapper select = wrapper.child();
            conditions.forEach(c -> condition(select, c, variables));
            //添加inSelect条件
            String inSelectSql = "SELECT " + trimBlank(fieldCode) + " FROM " + trimBlank(table) + " WHERE " + select.getSql();
            if (ConditionEnum.IN_SELECT == type) {
                wrapper.inSql(code, inSelectSql);
            } else {
                wrapper.notInSql(code, inSelectSql);
            }
        } else if (ConditionEnum.NOT_NULL == type) {
            wrapper.and(i -> i.apply(code + " is not null"));
        } else if (ConditionEnum.IS_NULL == type) {
            wrapper.and(i -> i.apply(code + " is null"));
        } else if (ConditionEnum.LE == type) {
            wrapper.le(code, value);
        } else if (ConditionEnum.LIKE == type) {
            wrapper.like(code, value);
        } else if (ConditionEnum.LIKE_LEFT == type) {
            wrapper.likeLeft(code, value);
        } else if (ConditionEnum.LIKE_RIGHT == type) {
            wrapper.likeRight(code, value);
        } else if (ConditionEnum.ORIGINALLIKE == type) {
            wrapper.likeNoLeftAndRight(true, code, value);
        } else if (ConditionEnum.LT == type) {
            wrapper.lt(code, value);
        } else if (ConditionEnum.NE == type) {
            wrapper.ne(code, value);
        } else if (ConditionEnum.AND == type || ConditionEnum.OR == type) {
            //获取组合条件
            List<Condition> conditions;
            if (p.getValue() instanceof JSONArray) {
                //json字符串类型
                conditions = JSON.parseArray(O2S.apply(p.getValue()), Condition.class);
            } else if (p.getValue() instanceof List) {
                //条件对象类型
                conditions = (List<Condition>) p.getValue();
            } else {
                //json字符串类型
                conditions = JSON.parseArray(O2S.apply(p.getValue()), Condition.class);
            }
            if (conditions.isEmpty()) {
                return;
            }
            //拼接组合条件
            Consumer<ConditionsWrapper> tConsumer = i -> {
                conditions.forEach(c -> condition(i, c, variables));
            };
            if (ConditionEnum.AND == type) {
                wrapper.and(tConsumer);
            } else {
                wrapper.or(tConsumer);
            }
        }
    }

    /**
     * Object 转 Collection
     *
     * @param value 待转换对象
     * @return 集合
     */
    public static List parseList(Object value) {

        List list = null;
        if (value instanceof List) {
            list = (List) value;
        } else if (value instanceof Object[]) {
            list = Arrays.asList((Object[]) value);
        } else if (value != null) {
            String str = O2S.apply(value);
            //json字符串类型
            try {
                list = JSONArray.parseArray(str);
            } catch (Exception e) {
                //异常情况视为逗号分隔数据
                list = Arrays.asList(str.split(","));
            }
        }
        return list;
    }

    public static Map<String, Object> systemVariable() {
        Map<String, Object> variables = new HashMap<>(64);
        EndUser currentUser = SecurityUserHolder.getCurrentUser();

        //------- 用户基础信息
        variables.put("@USER_ID@", currentUser.getUserId());
        variables.put("@JE.currentUser.userId@", currentUser.getUserId());
        variables.put("@USER_CODE@", currentUser.getUserCode());
        variables.put("@JE.currentUser.userCode@", currentUser.getUserCode());
        variables.put("@USER_NAME@", currentUser.getUsername());
        variables.put("@JE.currentUser.username@", currentUser.getUsername());

        variables.put("@USER_ROLEIDS@", currentUser.getRoleIds());
        variables.put("@JE.currentUser.roleIds@", currentUser.getRoleIds());
        variables.put("@USER_ROLECODES@", currentUser.getRoleCodes());
        variables.put("@JE.currentUser.roleCodes@", currentUser.getRoleCodes());
        variables.put("@USER_ROLENAMES@", currentUser.getRoleNames());
        variables.put("@JE.currentUser.roleNames@", currentUser.getRoleNames());
        variables.put("@USER_PHONE@", currentUser.getPhone());
        variables.put("@JE.currentUser.phone@", currentUser.getPhone());
        variables.put("@USER_JOBNUM@", currentUser.getJobNum());
        variables.put("@JE.currentUser.jobnum@", currentUser.getJobNum());
        variables.put("@USER_IDCARD@", currentUser.getIdCard());
        variables.put("@JE.currentUser.idCard@", currentUser.getIdCard());
        variables.put("@USER_COMPANYEMAIL@", currentUser.getCompanyEmail());
        variables.put("@JE.currentUser.companyEmail@", currentUser.getCompanyEmail());

        variables.put("@USER_JTGSMC@", currentUser.getJtgsMc());
        variables.put("@JE.currentUser.jtgsMc@", currentUser.getJtgsMc());
        variables.put("@USER_JTGSID@", currentUser.getJtgsId());
        variables.put("@JE.currentUser.jtgsId@", currentUser.getJtgsId());
        variables.put("@USER_ZHID@", currentUser.getZhId());
        variables.put("@JE.currentUser.zhId@", currentUser.getZhId());
        variables.put("@USER_ZHMC@", currentUser.getZhMc());
        variables.put("@JE.currentUser.zhMc@", currentUser.getZhMc());
        variables.put("@DEPT_ID@", currentUser.getDeptId());
        variables.put("@JE.currentUser.deptId@", currentUser.getDeptId());
        variables.put("@DEPT_CODE@", currentUser.getDeptCode());
        variables.put("@JE.currentUser.deptCode@", currentUser.getDeptCode());
        variables.put("@DEPT_NAME@", currentUser.getDeptName());
        variables.put("@JE.currentUser.deptName@", currentUser.getDeptName());
        variables.put("@DEPT_PATH@", currentUser.getDept().getPath());
        variables.put("@JE.currentUser.dept.path@", currentUser.getDept().getPath());
        variables.put("@DEPT_PARENT_ID@", currentUser.getDept().getParentId());
        variables.put("@JE.currentUser.dept.parentId@", currentUser.getDept().getParentId());
        variables.put("@IS_MANAGER@", currentUser.getIsManager());
        variables.put("@JE.currentUser.isManager@", currentUser.getIsManager());
        //------- TODO 做in处理
        //监管部门
        variables.put("@USER_MONITORDEPT@", currentUser.getMonitorDeptCode());
        //部门负责人
        variables.put("@USER_DEPTFZR@", currentUser.getDept().getChargeUser());
        //公司监管
        variables.put("@COMPANY_QUERYIDS@", currentUser.getDept().getJtjggsId());

        //------- 时间变量
        variables.put("@NOW_DATE@", DateUtils.formatDate(new Date()));
        variables.put("@NOW_MONTH@", DateUtils.formatDate(new Date(), "yyyy-MM"));
        variables.put("@NOW_TIME@", DateUtils.formatDateTime(new Date()));
        variables.put("@NOW_YEAR@", DateUtils.formatDate(new Date(), "yyyy"));
        variables.put("@NOW_ONLYMONTH@", DateUtils.formatDate(new Date(), "MM"));
        //添加系统变量
        Map<String, Object> allSysVar = WebUtils.getAllSysVar();
        Optional.ofNullable(allSysVar).ifPresent(variables::putAll);
        //添加前台变量
        Map<String, Object> frontVar = FrontCacheManager.getCacheValues();
        Optional.ofNullable(frontVar).ifPresent(variables::putAll);
        //添加后台变量
        Map<String, Object> backVar = BackCacheManager.getCacheValues();
        Optional.ofNullable(backVar).ifPresent(variables::putAll);
        return variables;
    }

    public static String formatVariable(ConditionsWrapper wrapper, Object sql) {
        return formatVariable(wrapper, sql, null);
    }

    public static String formatVariable(ConditionsWrapper wrapper, Object sql, Map<String, Object> values) {

        String sqlStr = O2S.apply(sql);
        Map<String, Object> variables = new HashMap<>(10);

        //添加默认变量
        Map<String, Object> systemVariable = systemVariable();
        Optional.ofNullable(systemVariable).ifPresent(variables::putAll);
        //添加变量
        Optional.ofNullable(values).ifPresent(variables::putAll);

        //值集合
        List<Object> matchValues = new ArrayList<>();

        //值匹配
        //'{var}'
        sqlStr = matchParameter(variables, matchValues, sqlStr, "('\\{(.*?)\\}')", 2, 2, 0);
        //'%{var}%'
        sqlStr = matchParameter(variables, matchValues, sqlStr, "('%\\{(.*?)\\}%')", 3, 3, 3);
        //'%{var}'
        sqlStr = matchParameter(variables, matchValues, sqlStr, "('%\\{(.*?)\\}')", 3, 2, 1);
        //'{var}%'
        sqlStr = matchParameter(variables, matchValues, sqlStr, "('\\{(.*?)\\}%')", 2, 3, 2);
        //"{var}"
        sqlStr = matchParameter(variables, matchValues, sqlStr, "(\"\\{(.*?)\\}\")", 2, 2, 0);
        //"%{var}%"
        sqlStr = matchParameter(variables, matchValues, sqlStr, "(\"%\\{(.*?)\\}%\")", 3, 3, 3);
        //"%{var}"
        sqlStr = matchParameter(variables, matchValues, sqlStr, "(\"%\\{(.*?)\\}\")", 3, 2, 1);
        //"{var}%"
        sqlStr = matchParameter(variables, matchValues, sqlStr, "(\"\\{(.*?)\\}%\")", 2, 3, 2);
        //{var}
        sqlStr = matchParameter(variables, matchValues, sqlStr, "(\\{(.*?)\\})", 1, 1, 0);

        //替换 #1#
        for (int i = 0; i < matchValues.size(); i++) {

            //值
            Object val = matchValues.get(i);
            //值集合
            List<Object> vals = null;
            if (val instanceof Collection) {
                //集合类型
                vals = new ArrayList<>((Collection<Object>) val);
            } else if (val.getClass().isArray()) {
                //数组类型
                vals = Arrays.asList((Object[]) val);
            }

            //放入 wrapper 后的key
            String key = null;
            if (vals == null) {
                key = wrapper.put(val);
            } else if (vals.isEmpty()) {
                key = wrapper.put(null);
            } else {
                //值为集合则
                StringBuilder keyBuilder = new StringBuilder();
                for (Object obj : vals) {
                    keyBuilder.append(wrapper.put(obj)).append(Conditions.COMMA);
                }
                //去掉末尾逗号
                keyBuilder.setLength(keyBuilder.length() - 1);
                key = keyBuilder.toString();
            }
            sqlStr = sqlStr.replaceAll(String.format("#@@%s@@#", i), key);
        }
        return sqlStr;
    }

    /**
     * 获取匹配的字符串
     *
     * @param variables 变量集合
     * @param values    值集合
     * @param sqlStr    sql语句
     * @param regex     正则
     * @param start     正则变量前置无效字符
     * @param end       正则变量后置无效字符
     * @param like      1:左like;2:右like;3:全like;不匹配:无like;
     * @return java.lang.String
     */
    public static String matchParameter(Map<String, Object> variables, List<Object> values, String sqlStr, String regex, int start, int end, int like) {
        Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
        Matcher matcher = pattern.matcher(sqlStr);
        while (matcher.find()) {
            String p = matcher.group();
            //变量名  @USER_CODE@,@USER.userId@ 等
            String parameter = p.substring(start, p.length() - end);
            parameter = parameter.replace("@USER.", "@JE.currentUser.");
            //获取值
            Object val = variables.get(parameter);
            //生成key
            String key = String.format("#@@%s@@#", values.size());
            //添加值
            switch (like) {
                case 1:
                    values.add("%" + val);
                    break;
                case 2:
                    values.add(val + "%");
                    break;
                case 3:
                    values.add("%" + val + "%");
                    break;
                default:
                    values.add(val);
            }
            //替换变量为key
            sqlStr = sqlStr.replace(p, key);
        }
        return sqlStr;
    }

    public static String formatSqlParameter(String sqlStr) {
        return formatSqlParameter(null, sqlStr);
    }

    /**
     * {var} 变量正则匹配
     */
    private static final Pattern pattern = Pattern.compile("(\\{(.*?)\\})", Pattern.MULTILINE);

    /**
     * 替换变量，直接赋值 非预处理
     *
     * @param values 自定义变量集合
     * @param sqlStr 语句
     * @return java.lang.String
     */
    public static String formatSqlParameter(Map<String, Object> values, String sqlStr) {
        //添加默认变量
        Map<String, Object> variables = systemVariable();
        //添加变量
        Optional.ofNullable(values).ifPresent(variables::putAll);
        Matcher matcher = pattern.matcher(sqlStr);
        while (matcher.find()) {
            String p = matcher.group();
            //变量名  @USER_CODE@,@USER.userId@ 等
            String parameter = p.substring(1, p.length() - 1);
            parameter = parameter.replace("@USER.", "@JE.currentUser.");
            //获取值
            Object val = variables.get(parameter);
            if (val != null) {
                sqlStr = sqlStr.replace(p, val.toString());
            }
        }
        return sqlStr;
    }

    /**
     * 去除sql开头的and或order
     *
     * @param sqlObject and 或 order by 开头的sql
     * @return java.lang.String
     */
    public static String trimSql(Object sqlObject) {
        if (sqlObject == null) {
            return null;
        }
        String sql = sqlObject.toString();
        String andStr = Conditions.AND.getSqlSegment();
        String orderStr = Conditions.ORDER_BY.getSqlSegment();

        String upperCase = sql.toUpperCase();
        if (upperCase.trim().startsWith(andStr)) {
            int and = upperCase.indexOf(andStr);
            return sql.substring(and + andStr.length(), sql.length());
        } else if (upperCase.trim().startsWith(orderStr)) {
            int order = upperCase.indexOf(orderStr);
            return sql.substring(order + orderStr.length(), sql.length());
        } else {
            return sql;
        }
    }

    /**
     * 去除字符串中所有空格
     *
     * @param str 字符串
     * @return java.lang.String
     */
    public static String trimBlank(String str) {
        if (str == null) {
            return null;
        } else {
            return str.replaceAll("\\s*", "");
        }
    }

    public ConditionsWrapper buildWrapper(Query query) {
        return buildWrapper(query, ConditionsWrapper.builder());
    }

    public ConditionsWrapper buildWrapper(Query query, ConditionsWrapper wrapper) {

        if (query == null) {
            return ConditionsWrapper.builder();
        }

        List<Condition> strategy = query.getStrategy();
        FuncQueryStrategy strategyBean = query.getStrategyBean();
        FuncPermVo funcPermVo = query.getFuncPermVo();
        String funcOrderSql = query.getFuncOrderSql();
        String funcWhereSql = query.getFuncWhereSql();
        List<Order> orders = query.getOrder();
        JSONObject formData = query.getFormData();

        //是否覆盖功能where语句
        boolean isOverride = query.isOverrideFuncWhere();

        //查询策略
        if (strategyBean != null) {
            //是否覆盖
            if ("1".equals(strategyBean.getIsOverride())) {
                isOverride = true;
            }
            //自定义js脚本优先级高于sql
            if (strategy != null && !strategy.isEmpty()) {
                wrapper.and(i -> {
                    strategy.forEach(p -> {
                        condition(i, p);
                    });
                });
            } else if (StringUtils.isNotBlank(strategyBean.getSql())) {
                wrapper.and(i -> i.apply(formatVariable(i, trimSql(strategyBean.getSql()))));
            }
        } else if (strategy != null && !strategy.isEmpty()) {
            wrapper.and(i -> {
                strategy.forEach(p -> {
                    condition(i, p);
                });
            });
        }

        //添加功能数据权限
        funcPermBuild(funcPermVo, wrapper);

        //添加功能whereSql
        if (!isOverride && StringUtils.isNotBlank(funcWhereSql)) {
            wrapper.and(i -> i.apply(formatVariable(i, trimSql(funcWhereSql))));
        }

        if (formData != null && "select".equals(formData.getString("__type"))) {
            //查询选择
            String fieldId = formData.getString("__fieldId");
            //获取配置
            if (StringUtils.isNotBlank(fieldId)) {

                String fieldConfig = "";

                if (StringUtils.isNotBlank(query.getAppId())) {
                    //app查询选择
                    JSONObject appFunc = query.getAppFunc();
                    //获取字段配置
                    JSONArray fields = appFunc.getJSONArray("fields");
                    for (int i = 0; i < fields.size(); i++) {
                        JSONObject field = fields.getJSONObject(i).getJSONObject("values");
                        if (field.equals(field.getString("JE_PHONE_APPFIELD_ID"))) {
                            fieldConfig = field.getString("APPFIELD_WHERESQL");
                            break;
                        }
                    }
                } else {
                    //pc查询选择
                    String selectConfigSql = "select RESOURCEFIELD_WHERESQL from JE_CORE_RESOURCEFIELD where JE_CORE_RESOURCEFIELD_ID = {0}";
                    List<Map<String, Object>> list = metaService.selectSql(selectConfigSql, fieldId);
                    if (list != null && !list.isEmpty() && list.get(0) != null) {
                        //查询选择配置的条件，有 Sq语句，condition数组 两种格式
                        fieldConfig = O2S.apply(list.get(0).get("RESOURCEFIELD_WHERESQL"));
                    }
                }

                //解析查询选择过滤条件配置
                if (StringUtils.isNotBlank(fieldConfig)) {
                    try {
                        //转换为条件数组
                        List<Condition> configs = JSON.parseArray(fieldConfig, Condition.class);
                        //变量
                        wrapper.and(configs != null && !configs.isEmpty(), i -> {
                            for (Condition p : configs) {
                                condition(i, p, formData);
                            }
                        });
                    } catch (JSONException e) {
                        //转换JSON失败视为 sql语句
                        String fieldConfigTemp = fieldConfig;
                        wrapper.and(i -> i.apply(formatVariable(i, trimSql(fieldConfigTemp), formData)));
                    }
                }
            }
        } else if (formData != null && "child".equals(formData.getString("__type"))) {
            //子功能
            String mainFuncId = formData.getString("__mainFuncId");
            String childFuncId = formData.getString("__childFuncId");
            if (StringUtils.isNotBlank(mainFuncId) && StringUtils.isNotBlank(childFuncId)) {
                String childConfigSql = "select * from JE_CORE_ASSOCIATIONFIELD where ASSOCIATIONFIELD_FID = {0} AND ASSOCIATIONFIELD_PID = {1}";
                DynaBean mainFunc = metaService.selectOneByPk("JE_CORE_FUNCINFO", mainFuncId);
                if (null != mainFunc) {
                    String mainFuncPkName = mainFunc.getStr("FUNCINFO_PKNAME");
                    String mainFuncTableName = mainFunc.getStr("FUNCINFO_TABLENAME");
                    addMainValuesToFormData(mainFuncPkName, mainFuncTableName, formData);
                }
                List<Map<String, Object>> childConfigs = metaService.selectSql(childConfigSql, mainFuncId, childFuncId);
                if (childConfigs != null && !childConfigs.isEmpty()) {
                    wrapper.and(i -> {
                        childConfigs.forEach(config -> {
                            //where条件 0或1
                            boolean whereCon = O2B.test(config.get("ASSOCIATIONFIELD_WHERECON"));
                            //传值 0或1
                            boolean transmit = O2B.test(config.get("ASSOCIATIONFIELD_TRANSMIT"));
                            //关联关系
                            String type = O2S.apply(config.get("ASSOCIATIONFIELD_ASSOCIATION"));
                            if (whereCon && StringUtils.isNotBlank(type)) {
                                //自定义sql
                                if ("IDIT".equalsIgnoreCase(type)) {
                                    String sql = O2S.apply(config.get("ASSOCIATIONFIELD_SQL"));
                                    //拼接自定义sql
                                    i.and(StringUtils.isNotBlank(sql), j -> j.apply(formatVariable(j, trimSql(sql), formData)));
                                } else if (transmit) {
                                    //子功能字段
                                    String code = O2S.apply(config.get("ASSOCIATIONFIELD_CHIFIELDCODE"));
                                    //主功能字段值
                                    Object value = formData.get(code);
                                    //拼接传值条件
                                    condition(i, new Condition(code, type, value));
                                }
                            }
                        });
                    });
                }
            }
        }

        //Condition转whereSql
        List<Condition> conditions = mixCondition(query);
        wrapper.and(conditions != null && !conditions.isEmpty(), i -> {
            conditions.forEach(p -> {
                condition(i, p);
            });
        });

        //mark处理
        List<Condition> mark = query.getMark();
        if (mark != null && !mark.isEmpty()) {
            //拼接条件
            ConditionsWrapper select = wrapper.child()
                    .eq("MARK_USERID", SecurityUserHolder.getCurrentUser().getUserId())
                    .eq("MARK_FUNCID", query.getFuncId())
                    .and(i -> {
                        mark.forEach(p -> {
                            condition(i, p);
                        });
                    });
            //添加inSelect条件
            String inSelectSql = String.format("SELECT MARK_MODELID FROM JE_CORE_MARK WHERE %s", select.getSql());
            wrapper.inSql(query.getFuncPkCode(), inSelectSql);
        }

        //添加自定义sql，此sql前端无法赋值
        String applySql = query.getApplySql();
        wrapper.and(StringUtils.isNotBlank(applySql), i -> {
            i.apply(trimSql(applySql));
        });

        //前端order条件
        StringBuffer orderBuffer = new StringBuffer();
        if (orders != null && !orders.isEmpty()) {
            String orderPattern = "\\s+(asc|desc)";
            Pattern pattern;
            Matcher matcher;
            boolean funcHasThisOrder;
            for (Order eachOrder : orders) {
                funcHasThisOrder = false;
                if (!Strings.isNullOrEmpty(funcOrderSql)) {
                    orderPattern = eachOrder.getCode().toLowerCase() + orderPattern;
                    pattern = Pattern.compile(orderPattern);
                    matcher = pattern.matcher(funcOrderSql.toLowerCase());
                    if (matcher.find()) {
                        funcHasThisOrder = true;
                    }
                }
                if (!funcHasThisOrder) {
                    orderBuffer.append(" ").append(trimBlank(eachOrder.getCode())).append(" ").append(trimBlank(eachOrder.getType())).append(",");
                }
            }
        }

        //功能orderSql
        if (StringUtils.isNotBlank(funcOrderSql)) {
            orderBuffer.append(" ").append(trimSql(funcOrderSql)).append(",");
        }

        //拼接order
        if (orderBuffer.length() > 0) {
            //删除末尾逗号
            orderBuffer.deleteCharAt(orderBuffer.length() - 1);
            //加入wrapper
            wrapper.apply(Conditions.ORDER_BY.getSqlSegment());
            wrapper.apply(orderBuffer.toString());
        }

        return wrapper;
    }

    private void addMainValuesToFormData(String mainFuncPkName, String mainFuncTableName, JSONObject formData) {
        if (Strings.isNullOrEmpty(formData.getString(mainFuncPkName))) {
            return;
        }
        DynaBean mainDynaBean = metaService.selectOneByPk(mainFuncTableName, formData.getString(mainFuncPkName));
        if (null == mainDynaBean) {
            return;
        }
        formData.putAll(mainDynaBean.getValues());
    }

    /**
     * 功能数据权限构建
     *
     * @param wrapper 条件对象
     */
    public void funcPermBuild(FuncPermVo funcPermVo, ConditionsWrapper wrapper) {
        //1.快速授权-控制字段
        //2.角色sql授权-sql授权
        if (funcPermVo != null) {
            //当前用户
            EndUser currentUser = SecurityUserHolder.getCurrentUser();
            List<DynaBean> rolesSql = funcPermVo.getRolesPerms();
            if (rolesSql != null && rolesSql.size() > 0) {
                String roles = currentUser.getRoleIds();
                for (DynaBean dynaBean : rolesSql) {
                    String roleid = dynaBean.getStr("PERM_ROLE_ID");
                    if (roles.indexOf(roleid) >= 0 && !Strings.isNullOrEmpty(dynaBean.getStr("PERM_TARGERVALUE"))) {
                        wrapper.and(i -> {
                            i.or(!i.isEmpty()).apply(formatVariable(i, trimSql(dynaBean.getStr("PERM_TARGERVALUE"))));
                        });
                    }
                }
            }

            //----判断是否使用数据权限Sql
            //可见人
            if (funcPermVo.getSeeUserIds().contains(currentUser.getUserId())) {
                return;
            }
            //可见部门
            if (funcPermVo.getSeeDeptIds().contains(currentUser.getDeptId())) {
                return;
            }
            //可见角色
            for (String roleId : funcPermVo.getSeeRoleIds()) {
                for (Role r : currentUser.getRoles()) {
                    if (r.getRoleId().equals(roleId)) {
                        return;
                    }
                }
            }
            //可见岗位
            for (String sentryId : funcPermVo.getSeeSentryIds()) {
                for (Sentry s : currentUser.getSentrys()) {
                    if (s.getSentryId().equals(sentryId)) {
                        return;
                    }
                }
            }

            wrapper.and(i -> {

                //覆盖默认数据权限sql
                boolean sqlOverwrite = false;

                //角色部门数据权限sql
                for (FuncSqlPermVo p : funcPermVo.getSqlPerms()) {
                    if (p.getSqlOverwrite()) {
                        sqlOverwrite = true;
                    }
                    //拼接sql
                    i.or(!i.isEmpty() && StringUtils.isNotBlank(p.getQuerySql())).apply(formatVariable(i, trimSql(p.getQuerySql())));
                }

                //功能默认数据权限
                if (!sqlOverwrite && StringUtils.isNotBlank(funcPermVo.getPermSql())) {
                    i.or(!i.isEmpty()).apply(formatVariable(i, trimSql(funcPermVo.getPermSql())));
                }

                //快速授权
                Set<String> permConfig = funcPermVo.getPermConfig();
                if (permConfig != null && !permConfig.isEmpty()) {
                    String userField = StringUtils.isBlank(funcPermVo.getUserField()) ? "SY_CREATEUSERID" : funcPermVo.getUserField();
                    String deptField = StringUtils.isBlank(funcPermVo.getDeptField()) ? "SY_CREATEORGID" : funcPermVo.getDeptField();
                    String jtgsField = StringUtils.isBlank(funcPermVo.getJtgsField()) ? "SY_JTGSID" : funcPermVo.getJtgsField();
                    //以下条件
                    for (String permType : permConfig) {

                        if ("SELF_CREATE".equals(permType)) {
                            //本人看本人
                            i.or(!i.isEmpty()).eq(userField, currentUser.getUserId());
                        } else if ("LEAD_DEPT".equals(permType)) {
                            //主管领导
                            UserLeader userLeader = currentUser.getBranchInfo();
                            List<String> zgLeaderIds;
                            //使用部门层次关系
                            if (!funcPermVo.getDeptCjIds().isEmpty()) {
                                zgLeaderIds = userLeader.getCjZglds().get(funcPermVo.getDeptCjIds().iterator().next());
                            } else {
                                zgLeaderIds = userLeader.getZgUserIds();
                            }
                            if (zgLeaderIds != null && !zgLeaderIds.isEmpty()) {
                                i.or(!i.isEmpty()).in(userField, zgLeaderIds);
                            }
                        } else if ("SELF_ZSDEPT".equals(permType)) {
                            //直属领导
                            UserLeader userLeader = currentUser.getBranchInfo();
                            List<String> zsLeaderIds = userLeader.getZsUserIds();
                            if (zsLeaderIds.size() > 0) {
                                i.or(!i.isEmpty()).in(userField, zsLeaderIds);
                            }

                        } else if ("SELF_FZRDEPT".equals(permType)) {
                            //部门负责人
                            UserLeader userLeader = currentUser.getBranchInfo();
                            List<String> fzrLeaderIds = userLeader.getFzrUserIds();
                            if (fzrLeaderIds.size() > 0) {
                                i.or(!i.isEmpty()).in(userField, fzrLeaderIds);
                            }
                        } else if ("MONITOR_DEPT".equals(permType)) {
                            //监管领导
                            UserLeader userLeader = currentUser.getBranchInfo();
                            List<String> jgLeaderIds;
                            //使用部门层次关系
                            if (!funcPermVo.getDeptCjIds().isEmpty()) {
                                jgLeaderIds = userLeader.getCjJgUserIds().get(funcPermVo.getDeptCjIds().iterator().next());
                            } else {
                                jgLeaderIds = userLeader.getJgUserIds();
                            }
                            if (jgLeaderIds != null && !jgLeaderIds.isEmpty()) {
                                i.or(!i.isEmpty()).in(userField, jgLeaderIds);
                            }
                        } else if ("SELF_DEPT".equals(permType)) {
                            //本部门可见
                            i.or(!i.isEmpty()).eq(deptField, currentUser.getDeptId());
                        } else if ("SELF_DEPT_PARENT".equals(permType)) {
                            //父级部门可见
                            String deptId = currentUser.getDeptId();
                            //找到当前人所在部门的子部门
                            List<DynaBean> child = DeptChildCacheManager.getCacheValue(deptId);
                            if (child == null) {
                                child = metaService.select("JE_CORE_DEPARTMENT", ConditionsWrapper.builder().like("PATH", deptId));
                                DeptChildCacheManager.putCache(deptId, child);
                            }
                            //提取子部门ID
                            List<String> deptIds = child.stream().map(p -> p.getStr("DEPTID")).collect(Collectors.toList());
                            deptIds.add(deptId);
                            i.or(!i.isEmpty()).in(deptField, deptIds);
                        } else if ("WF_PREAPPROV".equals(permType)) {
                            //待审批可见
                            i.or(!i.isEmpty()).like("SY_PREAPPROVUSERS", currentUser.getUserId());
                        } else if ("WF_APPROVED".equals(permType)) {
                            //审批过可见
                            i.or(!i.isEmpty()).like("SY_APPROVEDUSERS", currentUser.getUserId());
                        } else if ("SELF_COMPANY".equals(permType)) {
                            //本公司可见
                            i.or(!i.isEmpty()).eq(jtgsField, currentUser.getJtgsId());
                        } else if ("MONITOR_COMPANY".equals(permType)) {
                            //公司监管可见(公司)
                            if (funcPermVo.getUseCjglIds().size() > 0) {
                                DynaBean gsBean = funcPermManager.getYwcjPermSql(StringUtil.buildSplitString(ArrayUtils.getArray(funcPermVo.getUseCjglIds()), ","), "JTGS");
                                if (gsBean != null) {
                                    i.or(!i.isEmpty()).in(jtgsField, Arrays.asList(gsBean.getStr("JDGSINFO_JGGS_ID", "").split(",")));
                                }
                            }
//                        } else if ("MONITOR_COMPANY_DEPT".equals(permType)) {
//                            //公司监管部门可见
//                            if (funcPermVo.getUseCjglIds().size() > 0) {
//                                DynaBean gsBean = getYwcjPermSql(StringUtil.buildSplitString(ArrayUtils.getArray(funcPermVo.getUseCjglIds()), ","), "DEPT");
//                                if (gsBean != null) {
//                                    sql = gsBean.getStr("_WHERESQL_");
//                                }
//                            }
                        //TODO [feature]增加公司监管可见权限  张帅鹏
                        }else if ("MONITOR_COMPANY_DEPT".equals(permType)) {
//                            //公司监管部门可见
                            if(StringUtil.isNotEmpty(currentUser.getJgGsIds())) {
                                List<String> jgGsIds=new ArrayList<>();
                                for(String jgGs:currentUser.getJgGsIds().split(",")){
                                    if(StringUtil.isNotEmpty(jgGs)){
                                        jgGsIds.add(jgGs);
                                    }
                                }
                                i.or(!i.isEmpty()).in(jtgsField, jgGsIds);
                            }
                        }
                    }
                }
            });
        }
    }

    /**
     * 组合条件集合
     *
     * @param query 查询参数实体
     * @return java.util.List<com.je.core.mapper.query.Condition>
     */
    private List<Condition> mixCondition(Query query) {
        List<Condition> mixCondition = new ArrayList<>();
        Optional.ofNullable(query.getTree()).ifPresent(mixCondition::addAll);
        Optional.ofNullable(query.getQuick()).ifPresent(mixCondition::addAll);
        Optional.ofNullable(query.getGroup()).ifPresent(mixCondition::addAll);
        Optional.ofNullable(query.getColumn()).ifPresent(mixCondition::addAll);
        Optional.ofNullable(query.getWorkflow()).ifPresent(mixCondition::addAll);
        Optional.ofNullable(query.getCustom()).ifPresent(mixCondition::addAll);
        return mixCondition;
    }

}
